#ifndef RTTI
#define RTTI
#include <map>
#include <string>

namespace rtti {

/**
 * Copyright (c) 2016, 漆夜
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class Object;
class ClazzRegistration;

/**
 * @brief The Clazz class 描述类的顶层类
 */
class Clazz
{
public:
    /**
     * @brief TClazzMap key: 对象名称, value: 类型描述信息
     */
    typedef std::map<std::string, const Clazz *> TClazzMap;

public:
    /**
     * @brief new_instance 创建对应类型的实例对象
     * @return
     */
    virtual Object* new_instance() const
    {
        return NULL;
    }

    /**
     * @brief get_registry 获取对象列表
     * @return
     */
    static TClazzMap &get_registry()
    {
        static TClazzMap clazz_map;
        return clazz_map;
    }

    /**
     * @brief get_name 获取类型的名称
     * @return 类型名称
     */
    virtual std::string get_name() const = 0;

    /**
     * @brief for_name 通过名称得到对应类的描述类
     * @param className 类名
     * @return 描述类指针
     */
    static const Clazz *for_name(const std::string &className)
    {
        const Clazz* clazz = 0;
        TClazzMap::iterator iter = get_registry().find(className);
        if (iter != get_registry().end()) {
            clazz = get_registry()[className];
        }

        return clazz;
    }

    /**
     * @brief register_class 注册类信息
     * @param new_class 需要注册的类的描述类
     */
    static void register_class(const Clazz &new_class)
    {
        get_registry()[new_class.get_name()] = &new_class;
    }
};

/**
 * @brief The ClazzRegistration class 类型注册器
 */
class ClazzRegistration
{
public:
    typedef const Clazz &(*ClazzAccessor)();
    ClazzRegistration(ClazzAccessor accessor)
    {
        Clazz::register_class((*accessor)());
    }
};

/**
 * @brief The Object class 高级类的最高父类
 */
class Object
{
public:
    /**
     * @brief The ClazzObject class 高级类的描述累
     */
    class ClazzObject : public Clazz
    {
    public:
        ClazzObject(): Clazz() {}
        virtual ~ClazzObject() {}

        /**
         * @brief get_name 获取所描述类的类名
         * @return 类名
         */
        virtual std::string get_name() const
        {
            return std::string("Object");
        }

    };

    /**
     * @brief get_class 获取描述类
     * @return
     */
    virtual const Clazz &get_class() const
    {
        return Object::get_static_class();
    }

    /**
     * @brief get_static_class 获取描述类
     * @return
     */
    static const Clazz &get_static_class()
    {
        static ClazzObject the_class;
        return the_class;
    }

    /**
     * @brief register_class 注册当前类信息到高级类型表中TClazzMap
     * @return
     */
    static const ClazzRegistration &register_class()
    {
        static ClazzRegistration class_reg(Object::get_static_class);
        return class_reg;
    }

    /**
     * @brief instance_of 判断当前类是否是一个类的实例或派生类
     * @param clazz 需要检查的类信息
     * @return true/false
     */
    virtual bool instance_of(const Clazz &clazz) const = 0;

    /**
     * @brief cast 判断当前类是否是一个类的实例或派生类
     * @param clazz 需要检查的类信息
     * @return NULL表示不是
     */
    virtual const void *cast(const Clazz &clazz) const = 0;
public:
    Object() {}
    virtual ~Object() {}
};

}

/// @brief 添加一个类obj的描述信息
#define RTTI_DECLARE_OBJECT(obj) \
    public: \
        class Clazz##obj : public rtti::Clazz \
        { \
        public:\
            Clazz##obj() : Clazz() {} \
            virtual ~Clazz##obj() {} \
            virtual std::string get_name() const { return #obj; }\
            virtual obj* new_instance() const {return new obj(); }\
        }; \
        virtual const rtti::Clazz& get_class() const { return get_static_class(); } \
        static const rtti::Clazz& get_static_class() { static Clazz##obj the_class; return the_class; } \
        static const rtti::ClazzRegistration& register_class() { \
            static rtti::ClazzRegistration class_reg(obj::get_static_class); \
            return class_reg; \
        }

#define RTTI_DECLARE_OBJECT_WITH_ALIAS(obj, alias) \
    public: \
        class Clazz##obj : public rtti::Clazz \
        { \
        public:\
            Clazz##obj() : Clazz() {} \
            virtual ~Clazz##obj() {} \
            virtual std::string get_name() const { return #alias; }\
            virtual obj* new_instance() const {return new obj(); }\
        }; \
        virtual const rtti::Clazz& get_class() const { return get_static_class(); } \
        static const rtti::Clazz& get_static_class() { static Clazz##obj the_class; return the_class; } \
        static const rtti::ClazzRegistration& register_class() { \
            static rtti::ClazzRegistration class_reg(obj::get_static_class); \
            return class_reg; \
        }


/// @brief 注释当前类的派生关系
#define RTTI_BEGIN_CAST_MAP() \
    const void* cast(const rtti::Clazz &clazz) const { \
        const void * object = 0; \
        if (&clazz == &rtti::Object::get_static_class()) return (const rtti::Object*)this;

/// @brief 注释当前类是那些类的子类
#define RTTI_CAST_ENTRY(Interface) \
        if (&clazz == &Interface::get_static_class()) return (const Interface*)this;

/// @brief 注释当前类是那些类的子类
#define RTTI_CAST_ENTRY2(Interface, Interface2) \
        if (&clazz == &Interface::get_static_class()) return (Interface*)(Interface2 *)this;

/// @brief 注释当前类是那些类的子类链式计算
#define RTTI_CAST_ENTRY_CHAIN(Interface) \
    object = Interface::cast(clazz); \
    if (object != 0) return object;

/// @brief 描述信息书写完成
#define RTTI_END_CAST_MAP() \
        return object; \
    }\
    bool instance_of(const rtti::Clazz& clazz) const\
    { return cast(clazz) != 0; }

/// @brief 获取描述类
#define RTTI_TYPE_CLAZZ(Interface) Interface::get_static_class()

/// @brief 禁用拷贝构造方法和赋值方法
#define RTTI_DISABLE_COPY_CONSTRUCTION_AND_ASSIGNMENT(T) \
    private: \
        T(const T&); \
        T& operator=(const T&)

/// @brief 注册类型信息
#define RTTI_REIGSTER_CLASS(T) \
    namespace NS_RTTI_##T { \
        static const rtti::ClazzRegistration &T##_registration = T::register_class(); \
    }
#endif // RTTI

